//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
/********************************************************
    说明：
    1、外挂的SDRAM大小为8M字节。
    2、使用FMC_Bank2_SDRAM。
    3、对齐访问速度快，提供1字节读写、2字节读写、4字节读写。
    4、支持DMA读写SDRAM，自动字节对齐。（目前无法知道读写是否完成，放在后期在支持）
    5、基于stm32f4xx标准库V1.9.0
**********************************************************/

#ifndef __SDRAM_BSP_H__
#define __SDRAM_BSP_H__

#include "gd32f4xx.h"
#include "gd32f4xx_exmc.h"
#include "../GPIO_BSP/gpio_bsp.h"
#include "../DMA_BSP/dma_bsp.h"


#define IS42S16400J_SIZE  (64000000/8)  //8M字节

/*FMC SDRAM 数据基地址*/
#define SDRAM_BANK_ADDR     ((unsigned int)0xD0000000)



/*SDRAM 的bank选择*/  
#define FMC_BANK_SDRAM            EXMC_SDRAM_DEVICE0  
#define FMC_COMMAND_TARGET_BANK   EXMC_SDRAM_DEVICE0_SELECT

/*FMC SDRAM 数据宽度*/
#define SDRAM_MEMORY_WIDTH        EXMC_SDRAM_DATABUS_WIDTH_16B 

/*FMC SDRAM CAS Latency*/
#define SDRAM_CAS_LATENCY         EXMC_CAS_LATENCY_3_SDCLK

/*FMC SDRAM SDCLK时钟分频因子*/
#define SDCLOCK_PERIOD            EXMC_SDCLK_PERIODS_3_HCLK  /* 与LCD配合使用的默认配置 */

/*FMC SDRAM 突发读取特性*/
#define SDRAM_READBURST           ENABLE
//#define SDRAM_READBURST         DISABLE /* 与LCD配合使用的默认配置 */



/*FMC SDRAM 模式配置的寄存器相关定义*/
#define SDRAM_MODEREG_BURST_LENGTH_1             ((unsigned short)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2             ((unsigned short)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4             ((unsigned short)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8             ((unsigned short)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((unsigned short)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((unsigned short)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2              ((unsigned short)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3              ((unsigned short)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((unsigned short)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((unsigned short)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((unsigned short)0x0200)

/*A行列地址信号线*/    
#define FMC_A0_GPIO_PORT        PortF
#define FMC_A0_GPIO_PIN         Pin0

#define FMC_A1_GPIO_PORT        PortF
#define FMC_A1_GPIO_PIN         Pin1

#define FMC_A2_GPIO_PORT        PortF
#define FMC_A2_GPIO_PIN         Pin2

#define FMC_A3_GPIO_PORT        PortF
#define FMC_A3_GPIO_PIN         Pin3

#define FMC_A4_GPIO_PORT        PortF
#define FMC_A4_GPIO_PIN         Pin4

#define FMC_A5_GPIO_PORT        PortF
#define FMC_A5_GPIO_PIN         Pin5

#define FMC_A6_GPIO_PORT        PortF
#define FMC_A6_GPIO_PIN         Pin12

#define FMC_A7_GPIO_PORT        PortF
#define FMC_A7_GPIO_PIN         Pin13

#define FMC_A8_GPIO_PORT        PortF
#define FMC_A8_GPIO_PIN         Pin14

#define FMC_A9_GPIO_PORT        PortF
#define FMC_A9_GPIO_PIN         Pin15

#define FMC_A10_GPIO_PORT       PortG
#define FMC_A10_GPIO_PIN        Pin0

#define FMC_A11_GPIO_PORT       PortG
#define FMC_A11_GPIO_PIN        Pin1

/*BA地址线*/
#define FMC_BA0_GPIO_PORT       PortG
#define FMC_BA0_GPIO_PIN        Pin4

#define FMC_BA1_GPIO_PORT       PortG
#define FMC_BA1_GPIO_PIN        Pin5

/*DQ数据信号线*/
#define FMC_D0_GPIO_PORT        PortD
#define FMC_D0_GPIO_PIN         Pin14

#define FMC_D1_GPIO_PORT        PortD
#define FMC_D1_GPIO_PIN         Pin15

#define FMC_D2_GPIO_PORT        PortD
#define FMC_D2_GPIO_PIN         Pin0

#define FMC_D3_GPIO_PORT        PortD
#define FMC_D3_GPIO_PIN         Pin1

#define FMC_D4_GPIO_PORT        PortE
#define FMC_D4_GPIO_PIN         Pin7

#define FMC_D5_GPIO_PORT        PortE
#define FMC_D5_GPIO_PIN         Pin8

#define FMC_D6_GPIO_PORT        PortE
#define FMC_D6_GPIO_PIN         Pin9

#define FMC_D7_GPIO_PORT        PortE
#define FMC_D7_GPIO_PIN         Pin10

#define FMC_D8_GPIO_PORT        PortE
#define FMC_D8_GPIO_PIN         Pin11

#define FMC_D9_GPIO_PORT        PortE
#define FMC_D9_GPIO_PIN         Pin12

#define FMC_D10_GPIO_PORT       PortE
#define FMC_D10_GPIO_PIN        Pin13

#define FMC_D11_GPIO_PORT       PortE
#define FMC_D11_GPIO_PIN        Pin14

#define FMC_D12_GPIO_PORT       PortE
#define FMC_D12_GPIO_PIN        Pin15

#define FMC_D13_GPIO_PORT       PortD
#define FMC_D13_GPIO_PIN        Pin8

#define FMC_D14_GPIO_PORT       PortD
#define FMC_D14_GPIO_PIN        Pin9

#define FMC_D15_GPIO_PORT       PortD
#define FMC_D15_GPIO_PIN        Pin10

/*控制信号线*/  
/*CS片选*/
#define FMC_CS_GPIO_PORT        PortH
#define FMC_CS_GPIO_PIN         Pin6

/*WE写使能*/
#define FMC_WE_GPIO_PORT        PortC
#define FMC_WE_GPIO_PIN         Pin0
/*RAS行选通*/
#define FMC_RAS_GPIO_PORT       PortF
#define FMC_RAS_GPIO_PIN        Pin11
/*CAS列选通*/
#define FMC_CAS_GPIO_PORT       PortG
#define FMC_CAS_GPIO_PIN        Pin15
/*CLK同步时钟，存储区域2*/
#define FMC_CLK_GPIO_PORT       PortG
#define FMC_CLK_GPIO_PIN        Pin8
/*CKE时钟使能，存储区域2*/
#define FMC_CKE_GPIO_PORT       PortH
#define FMC_CKE_GPIO_PIN        Pin7

/*DQM1数据掩码*/
#define FMC_UDQM_GPIO_PORT      PortE
#define FMC_UDQM_GPIO_PIN       Pin1
/*DQM0数据掩码*/
#define FMC_LDQM_GPIO_PORT      PortE
#define FMC_LDQM_GPIO_PIN       Pin0


/*SDRAM回调函数结构体*/
typedef struct
{
    ErrStatus (*WHT_Register)(void);
    void (*WHT_Write_1Byte)(const unsigned char* buffer, unsigned int address, unsigned int length);
    void (*WHT_Write_2Byte)(const unsigned short* buffer, unsigned int address, unsigned int length);
    void (*WHT_Write_4Byte)(const unsigned int* buffer, unsigned int address, unsigned int length);
    void (*WHT_Read_1Byte)(unsigned char* buffer, unsigned int address, unsigned int length);
    void (*WHT_Read_2Byte)(unsigned short* buffer, unsigned int address, unsigned int length);
    void (*WHT_Read_4Byte)(unsigned int* buffer, unsigned int address, unsigned int length);
    /*无法知道传输是否完成，用户在拷贝前自定义最后一个数据，检测最后一个数据是否一致即可
      建议用户评估时间加入阻塞延迟
    */
    void (*WHT_Write_DMA)(const void* buffer, unsigned int address, unsigned int size);
    void (*WHT_Read_DMA)(void* buffer, unsigned int address, unsigned int size);
}WHT_SDRAM_BSP_t;

/*全局常量*/
extern const WHT_SDRAM_BSP_t WHT_SDRAM_BSP;

#endif /*__SDRAM_BSP_H__*/
